"""
引用标注分析器
用于识别引用模式并生成引用建议
"""
import re
from typing import List, Dict, Any, Optional, Tuple
from enum import Enum
from dataclasses import dataclass, field
from datetime import datetime


class CitationFormat(Enum):
    """引用格式枚举"""
    APA = "apa"
    MLA = "mla"
    CHICAGO = "chicago"
    GB7714 = "gb7714"  # 中国国家标准


@dataclass
class Citation:
    """引用信息数据类"""
    text: str  # 引用内容
    start_pos: int  # 起始位置
    end_pos: int  # 结束位置
    type: str  # 引用类型：quote, paraphrase, reference
    confidence: float  # 置信度
    suggested_format: Optional[str] = None  # 建议的引用格式
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class CitationSuggestion:
    """引用建议数据类"""
    text: str  # 需要标注的文本
    start_pos: int
    end_pos: int
    reason: str  # 建议原因
    priority: str  # 优先级：high, medium, low
    suggested_citation: Optional[str] = None


class CitationAnalyzer:
    """引用分析器"""
    
    # 引用模式正则表达式
    CITATION_PATTERNS = {
        # 中文引号模式
        'chinese_quote': re.compile(r'[""]([^""]+)[""]'),
        'chinese_book_quote': re.compile(r'[《]([^》]+)[》]'),
        
        # 英文引号模式
        'english_quote': re.compile(r'["\']([^"\']+)["\']'),
        
        # 括号引用模式 (Author, Year) 或 (作者, 年份)
        'parenthetical': re.compile(r'\(([^)]*\d{4}[^)]*)\)'),
        
        # 脚注模式 [1] 或 ¹
        'footnote': re.compile(r'\[(\d+)\]|[¹²³⁴⁵⁶⁷⁸⁹⁰]+'),
        
        # 常见引用词汇 - 使用词边界避免误匹配
        'citation_keywords': re.compile(
            r'\b(根据|按照|引用|参考|来源于|摘自|转载自|cited from|according to|based on|referenced from)\b',
            re.IGNORECASE
        ),
        
        # 学术引用模式 et al., 等人
        'academic': re.compile(r'([A-Za-z\u4e00-\u9fa5]+\s*(et al\.|等人|等)\s*[,，]\s*\d{4})'),
    }
    
    # 需要引用的特征词
    CITATION_INDICATORS = [
        '研究表明', '研究发现', '调查显示', '数据显示',
        '统计表明', '实验证明', '报告指出', '论文中提到',
        'studies show', 'research indicates', 'survey reveals',
        'data shows', 'statistics indicate', 'experiments prove'
    ]
    
    def __init__(self, format_type: CitationFormat = CitationFormat.APA):
        """
        初始化引用分析器
        
        Args:
            format_type: 默认引用格式类型
        """
        self.format_type = format_type
    
    def analyze(self, text: str) -> Dict[str, Any]:
        """
        分析文本中的引用
        
        Args:
            text: 待分析文本
            
        Returns:
            分析结果字典
        """
        citations = self.identify_citations(text)
        suggestions = self.generate_suggestions(text, citations)
        
        return {
            'citations': citations,
            'suggestions': suggestions,
            'total_citations': len(citations),
            'needs_citation_count': len(suggestions),
            'citation_coverage': self._calculate_coverage(text, citations),
            'format_type': self.format_type.value
        }
    
    def identify_citations(self, text: str) -> List[Citation]:
        """
        识别文本中的引用
        
        Args:
            text: 待分析文本
            
        Returns:
            引用列表
        """
        citations = []
        
        # 检查各种引用模式
        for pattern_name, pattern in self.CITATION_PATTERNS.items():
            for match in pattern.finditer(text):
                citation_type = self._get_citation_type(pattern_name)
                citation = Citation(
                    text=match.group(0),
                    start_pos=match.start(),
                    end_pos=match.end(),
                    type=citation_type,
                    confidence=self._calculate_confidence(match, pattern_name),
                    metadata={'pattern': pattern_name}
                )
                citations.append(citation)
        
        # 去重和合并重叠的引用
        citations = self._merge_overlapping_citations(citations)
        
        return citations
    
    def generate_suggestions(self, text: str, existing_citations: List[Citation]) -> List[CitationSuggestion]:
        """
        生成引用建议
        
        Args:
            text: 原文本
            existing_citations: 已识别的引用
            
        Returns:
            引用建议列表
        """
        suggestions = []
        
        # 分句处理
        sentences = self._split_sentences(text)
        
        for sentence_text, start_pos in sentences:
            # 检查是否需要引用
            if self._needs_citation(sentence_text, existing_citations, start_pos):
                priority = self._calculate_priority(sentence_text)
                suggestion = CitationSuggestion(
                    text=sentence_text,
                    start_pos=start_pos,
                    end_pos=start_pos + len(sentence_text),
                    reason=self._get_suggestion_reason(sentence_text),
                    priority=priority,
                    suggested_citation=self._generate_citation_template(sentence_text)
                )
                suggestions.append(suggestion)
        
        return suggestions
    
    def format_citation(self, author: str, year: int, title: str, 
                       source: Optional[str] = None,
                       format_type: Optional[CitationFormat] = None) -> str:
        """
        格式化引用
        
        Args:
            author: 作者
            year: 年份
            title: 标题
            source: 来源
            format_type: 引用格式类型
            
        Returns:
            格式化后的引用文本
        """
        format_type = format_type or self.format_type
        
        if format_type == CitationFormat.APA:
            citation = f"{author} ({year}). {title}."
            if source:
                citation += f" {source}."
        
        elif format_type == CitationFormat.MLA:
            citation = f'{author}. "{title}."'
            if source:
                citation += f" {source},"
            citation += f" {year}."
        
        elif format_type == CitationFormat.CHICAGO:
            citation = f'{author}. "{title}."'
            if source:
                citation += f" {source}"
            citation += f" ({year})."
        
        elif format_type == CitationFormat.GB7714:
            citation = f"{author}. {title}[J]."
            if source:
                citation += f" {source},"
            citation += f" {year}."
        
        return citation
    
    def auto_format(self, text: str, citations_data: List[Dict[str, Any]]) -> str:
        """
        自动格式化文本中的引用
        
        Args:
            text: 原文本
            citations_data: 引用数据列表
            
        Returns:
            格式化后的文本
        """
        result = text
        offset = 0
        
        # 按位置排序
        sorted_citations = sorted(citations_data, key=lambda x: x.get('position', 0))
        
        for citation_info in sorted_citations:
            position = citation_info.get('position', 0) + offset
            formatted_citation = self.format_citation(
                author=citation_info.get('author', 'Unknown'),
                year=citation_info.get('year', datetime.now().year),
                title=citation_info.get('title', 'Untitled'),
                source=citation_info.get('source')
            )
            
            # 在指定位置插入格式化的引用
            result = result[:position] + f" ({formatted_citation})" + result[position:]
            offset += len(f" ({formatted_citation})")
        
        return result
    
    def _get_citation_type(self, pattern_name: str) -> str:
        """获取引用类型"""
        if 'quote' in pattern_name:
            return 'quote'
        elif 'parenthetical' in pattern_name or 'footnote' in pattern_name:
            return 'reference'
        elif 'academic' in pattern_name:
            return 'academic'
        else:
            return 'general'
    
    def _calculate_confidence(self, match: re.Match, pattern_name: str) -> float:
        """计算引用识别的置信度"""
        base_confidence = 0.5
        
        # 引号类型置信度高
        if 'quote' in pattern_name:
            base_confidence = 0.9
        # 学术引用置信度高
        elif 'academic' in pattern_name or 'parenthetical' in pattern_name:
            base_confidence = 0.85
        # 脚注置信度中等
        elif 'footnote' in pattern_name:
            base_confidence = 0.7
        
        # 根据匹配长度调整
        match_length = len(match.group(0))
        if match_length > 50:
            base_confidence *= 0.95
        elif match_length < 5:
            base_confidence *= 0.8
        
        return min(base_confidence, 1.0)
    
    def _merge_overlapping_citations(self, citations: List[Citation]) -> List[Citation]:
        """合并重叠的引用"""
        if not citations:
            return []
        
        # 按起始位置排序
        sorted_citations = sorted(citations, key=lambda x: x.start_pos)
        merged = [sorted_citations[0]]
        
        for current in sorted_citations[1:]:
            last = merged[-1]
            
            # 检查是否重叠
            if current.start_pos <= last.end_pos:
                # 合并，取置信度更高的
                if current.confidence > last.confidence:
                    merged[-1] = current
            else:
                merged.append(current)
        
        return merged
    
    def _split_sentences(self, text: str) -> List[Tuple[str, int]]:
        """分句并返回句子和位置"""
        sentences = []
        # 中英文句子分割
        pattern = re.compile(r'[。！？.!?]+')
        
        last_end = 0
        for match in pattern.finditer(text):
            sentence = text[last_end:match.end()].strip()
            if sentence:
                sentences.append((sentence, last_end))
            last_end = match.end()
        
        # 处理最后一个句子
        if last_end < len(text):
            sentence = text[last_end:].strip()
            if sentence:
                sentences.append((sentence, last_end))
        
        return sentences
    
    def _needs_citation(self, sentence: str, existing_citations: List[Citation], 
                        start_pos: int) -> bool:
        """判断句子是否需要引用"""
        # 检查是否已有引用
        sentence_end = start_pos + len(sentence)
        for citation in existing_citations:
            # 检查引用是否在句子范围内
            if (start_pos <= citation.start_pos < sentence_end or 
                start_pos < citation.end_pos <= sentence_end):
                return False
        
        # 检查是否包含需要引用的特征词
        for indicator in self.CITATION_INDICATORS:
            if indicator in sentence.lower():
                return True
        
        # 检查是否包含数字统计信息
        if re.search(r'\d+[%％]|\d+\s*[人个名位]|[一二三四五六七八九十百千万亿]+[人个名位]', sentence):
            return True
        
        return False
    
    def _calculate_priority(self, sentence: str) -> str:
        """计算建议优先级"""
        # 包含具体数据的优先级高
        if re.search(r'\d+[%％]|\d+\s*[人个名位]', sentence):
            return 'high'
        
        # 包含研究/调查等词的优先级中
        for indicator in self.CITATION_INDICATORS[:8]:  # 前8个是中文指标
            if indicator in sentence:
                return 'medium'
        
        return 'low'
    
    def _get_suggestion_reason(self, sentence: str) -> str:
        """获取建议原因"""
        if re.search(r'\d+[%％]|\d+\s*[人个名位]', sentence):
            return "包含具体数据，需要标注来源"
        
        for indicator in self.CITATION_INDICATORS:
            if indicator in sentence:
                return f"包含'{indicator}'，建议添加引用"
        
        return "该内容可能需要引用支持"
    
    def _generate_citation_template(self, sentence: str) -> str:
        """生成引用模板"""
        if self.format_type == CitationFormat.APA:
            return "(Author, Year)"
        elif self.format_type == CitationFormat.MLA:
            return "(Author Page)"
        elif self.format_type == CitationFormat.GB7714:
            return "[作者. 标题[J]. 期刊, 年份.]"
        else:
            return "[Citation needed]"
    
    def _calculate_coverage(self, text: str, citations: List[Citation]) -> float:
        """计算引用覆盖率"""
        if not text:
            return 0.0
        
        cited_chars = 0
        for citation in citations:
            cited_chars += citation.end_pos - citation.start_pos
        
        return min(cited_chars / len(text), 1.0)